﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GDD2_Game3
{
	delegate void Effect(Vehicle vehicle, Track track);
	class PowerUp : GameObject
	{
		private static IList<Effect> unDistributedEffects;
		private static IList<PowerUp> powerUps;
		public Effect effect;
		public bool Enabled { get; set; }
		private static Random random;
		private static IDictionary<Effect, string> effectToString;

		static PowerUp()
		{
			powerUps = new List<PowerUp>();
			random = new Random();
			effectToString = new Dictionary<Effect, string>();
			effectToString.Add(HinderRandomKey, "One of your control keys is tired...");
			effectToString.Add(UnHinderAllKeys, "Your keys are now alert and upright as ever!");
			effectToString.Add(RemovePowerUps, "No more effect tiles, :-(");
			effectToString.Add(ChangePowerUpsToWalls, "Effect tiles have mutated into walls!");
			effectToString.Add(TeleportToPowerUp, "Effect tile portals!");
			effectToString.Add(CanMoveThroughWalls, "You can now move through walls...slowly.");
			effectToString.Add(MoveFaster, "Weeee! Faaast!");
			effectToString.Add(TurnFaster, "Gotta rotate fast!");
			effectToString.Add(PedalToTheMetal, "Don't need no stinkin' 'W' button!");
			effectToString.Add(PhaycFizix, "Are these racing controls?");
			effectToString.Add(FullBounce, "Bouncy walls!");
			effectToString.Add(NotBounce, "Bye bye, wall recoil!");
			effectToString.Add(ReverseControls, "Do you like inverted controls?");
			effectToString.Add(MoarRotation, "A revolution in rotation!");
			effectToString.Add(RemoveRandomWalls, "Walls are now 20% off!");
			effectToString.Add(ShrinkVehicle, "Honey, I shrunk the car!");
			effectToString.Add(RandomPowerUpToFinish, "A random effect tile is now a possible finish location!");
			effectToString.Add(NoOp, "Nothing happened.");
			unDistributedEffects = new List<Effect>(effectToString.Keys);
			
		}

		public PowerUp(float x, float y, float width, float height)
			: base(x, y, width, height)
		{
			powerUps.Add(this);
			int index = random.Next(unDistributedEffects.Count);
			effect = unDistributedEffects[index];
			unDistributedEffects.RemoveAt(index);
			Enabled = true;
		}

		public string update(Vehicle vehicle, Track track)
		{
			if(colliding(vehicle) && Enabled)
			{
				effect(vehicle, track);
				Enabled = false;
				return effectToString[effect];
			}
			return null;
		}

		private static void HinderRandomKey(Vehicle vehicle, Track track)
		{
			vehicle.KeysHindered |= new Vehicle.Keys[] { Vehicle.Keys.A, Vehicle.Keys.S, Vehicle.Keys.D }[random.Next(3)];
		}

		private static void UnHinderAllKeys(Vehicle vehicle, Track track)
		{
			vehicle.KeysHindered = Vehicle.Keys.None;
			vehicle.ReversedControls = false;
		}

		private static void RemovePowerUps(Vehicle vehicle, Track track)
		{
			track.PowerUps.Clear();
		}

		private static void ChangePowerUpsToWalls(Vehicle vehicle, Track track)
		{
			foreach(PowerUp powerUp in track.PowerUps)
			{
				track.Walls.Add(new Wall(powerUp.Box.Center.X, powerUp.Box.Center.Y, powerUp.Box.Dimensions.X, powerUp.Box.Dimensions.Y));
			}
			track.PowerUps.Clear();
		}

		private static void TeleportToPowerUp(Vehicle vehicle, Track track)
		{
			vehicle.teleport(powerUps[random.Next(powerUps.Count)].Box.Center);
		}

		private static void CanMoveThroughWalls(Vehicle vehicle, Track track)
		{
			foreach(Wall wall in track.Walls)
			{
				wall.CanMoveThrough = true;
			}
		}

		private static void MoveFaster(Vehicle vehicle, Track track)
		{
			vehicle.IsFaster = true;
		}

		private static void TurnFaster(Vehicle vehicle, Track track)
		{
			vehicle.TurnsFaster = true;
		}

		private static void PedalToTheMetal(Vehicle vehicle, Track track)
		{
			vehicle.AlwaysMoving = true;
		}

		private static void NotBounce(Vehicle vehicle, Track track)
		{
			foreach(Wall wall in track.Walls)
			{
				wall.FullBounce = false;
				wall.NonBounce = true;
			}
		}

		private static void FullBounce(Vehicle vehicle, Track track)
		{
			foreach(Wall wall in track.Walls)
			{
				wall.FullBounce = true;
				wall.NonBounce = false;
			}
		}

		private static void PhaycFizix(Vehicle vehicle, Track track)
		{
			vehicle.FakePhysics = true;
		}

		private static void ReverseControls(Vehicle vehicle, Track track)
		{
			vehicle.ReversedControls = !vehicle.ReversedControls;
		}

		private static void MoarRotation(Vehicle vehicle, Track track)
		{
			vehicle.ConstantRotation += (random.Next(2) == 0.0f ? -1.0f : 1.0f) * Convert.ToSingle(Math.PI) / 18.0f;
		}

		private static void RemoveRandomWalls(Vehicle vehicle, Track track)
		{
			for(int i = 0; i < track.Walls.Count; ++i)
			{
				if(random.Next(5) == 0)
				{
					track.Walls.RemoveAt(i);
					--i;
				}
			}
		}

		private static void ShrinkVehicle(Vehicle vehicle, Track track)
		{
			vehicle.shrinkCarByHalf();
		}

		private static void RandomPowerUpToFinish(Vehicle vehicle, Track track)
		{
			int index = random.Next(track.PowerUps.Count);
			track.Finish.Add(new FinishLine(track.PowerUps[index].box.Center.X, track.PowerUps[index].box.Center.Y, track.PowerUps[index].box.Dimensions.X, track.PowerUps[index].box.Dimensions.Y));
			track.PowerUps.RemoveAt(index);
		}

		private static void NoOp(Vehicle vehicle, Track track)
		{
			track.decreaseGameTime(2.0);
		}
	}
}
